Multi-category dot-density maps often work well when the categories cluster geographically. Recent immigrants by country of origin work well for this. ## Data First we grab the immigrant data via cancensus, making use of the CensusMapper API tool to select the regions and variables we need.

#devtools::install_github("mountainmath/cancensus")
library(cancensus)
library(dotdensity)
# options(cancensus.api_key='your_api_key')
regions=list(CMA="59933")
vectors_2011=c("v_CA11N_265","v_CA11N_268","v_CA11N_304","v_CA11N_334","v_CA11N_373","v_CA11N_376","v_CA11N_379","v_CA11N_382")
vectors=c("v_CA16_3636","v_CA16_3639","v_CA16_3669","v_CA16_3699","v_CA16_3741","v_CA16_3810","v_CA16_3750","v_CA16_3756","v_CA16_3783")

We choose the categories and colours we want to map and define a convenience function to rename the variables and compute the qantities for the other asian countries that we don’t break out.

categories=c("Americas","Europe","Africa + Oceania","Philippines","China","India","Other Asian Countries")
colors=c("#7a0177", "#3333cc", "#ff00ff", "#00ffff", "#ff1a1c", "#4dff4a", "#ffff33")
prep_data <- function(geo){
  data <- geo@data %>% replace(is.na(.), 0)
  data <- rename(data,
    total=v_CA16_3636,
    Americas=v_CA16_3639,                                  
    Europe=v_CA16_3669,
    Philippines=v_CA16_3783,
    China=v_CA16_3750,
    India=v_CA16_3756)
  data <- mutate(data,`Other Asian Countries` = v_CA16_3741-Philippines-China-India,
                     `Africa + Oceania`=v_CA16_3699 + v_CA16_3810)
  geo@data <- data
  return(geo)
}
prep_data_2011 <- function(geo){
  data <- geo@data %>% replace(is.na(.), 0)
  data <- rename(data,
    total=v_CA11N_265,
    Americas=v_CA11N_268,                                  
    Europe=v_CA11N_304,
    Africa=v_CA11N_334,
    Philippines=v_CA11N_376,
    China=v_CA11N_379,
    India=v_CA11N_382)
  data <- mutate(data,`Other Asian Countries` = v_CA11N_373-Philippines-China-India)
  geo@data <- data
  return(geo)
}

Next we grab the data via cancensus,

data_csd=get_census(dataset = 'CA16', regions=regions,vectors=vectors,geo_format='sp',labels='short',level='CSD') %>% prep_data
OGR data source with driver: GeoJSON 
Source: "/Users/jens/.cancensus_cache/CM_geo_6b42dc9bcf266cb7c9bfbbbf40889c49.geojson", layer: "OGRGeoJSON"
with 39 features
It has 11 fields
data_ct=get_census(dataset = 'CA16', regions=regions,vectors=vectors,geo_format='sp',labels='short',level='CT') %>% prep_data
OGR data source with driver: GeoJSON 
Source: "/Users/jens/.cancensus_cache/CM_geo_4a5626a6774fefc22c656038b44803a8.geojson", layer: "OGRGeoJSON"
with 478 features
It has 11 fields
data_da=get_census(dataset = 'CA16', regions=regions,vectors=vectors,geo_format='sp',labels='short',level='DA') %>% prep_data
OGR data source with driver: GeoJSON 
Source: "/Users/jens/.cancensus_cache/CM_geo_e0f185a0c335b032df17fa063ccc9238.geojson", layer: "OGRGeoJSON"
with 3450 features
It has 10 fields
data_db=get_census(dataset = 'CA16', regions=regions,geo_format='sp',labels='short',level='DB')
OGR data source with driver: GeoJSON 
Source: "/Users/jens/.cancensus_cache/CM_geo_ebd06436dd29d8db88d687516f5a8c04.geojson", layer: "OGRGeoJSON"
with 15197 features
It has 10 fields

which we then re-aggregate to make sure we don’t miss overall counts due to privacy cutoffs distribute them proportionally among the population.

data_ct@data <- dot_density.proportional_re_aggregate(data=data_ct@data,parent_data=data_csd@data,geo_match=setNames("GeoUID","CSD_UID"),categories=categories,base="Population")
data_da@data <- dot_density.proportional_re_aggregate(data=data_da@data,parent_data=data_ct@data,geo_match=setNames("GeoUID","CT_UID"),categories=categories,base="Population")
data_db@data <- dot_density.proportional_re_aggregate(data=data_db@data,parent_data=data_da@data,geo_match=setNames("GeoUID","DA_UID"),categories=categories,base="Population")

Map

All that’s left to do is to covert our re-aggregated block-level data to dots, using the dot_density.compute_dots function from the dotdensity package and feed it into the dot_density.dots_map function to add them to our basemap.

# 1 dot = 5 immigrants
scale=5
dots.db <- dot_density.compute_dots(geo_data = data_db, categories = categories, scale=scale)
basemap +
  # zoom in a bit
  coord_fixed(xlim=c(-123.29,-122.6), ylim=c(49.02,49.35), ratio = 1/cos(49.2/180*pi)) +
# shade unpopulated blocks
#  geom_polygon(data=data_db[data_db$Population<=5,], 
#                        aes(long, lat, group = group), 
#                        fill = "#222222", size=0.1, 
#                        color = "#222222") +
  scale_colour_manual(values = colors) +
  labs(color = "",
                title="Immigrants 2011 - 2016",
                caption="Source: StatCan Census 2016 via cancensus & CensusMapper.ca",
                subtitle = paste0("1 dot = ",scale," people")) + 
  dot_density.dots_map(dots=dots.db,alpha=0.75,size=0.25)

# save image for later
ggsave('../images/recent_immigrants.png',width=26,height=26)
LS0tCnRpdGxlOiAiUmVjZW50IEltbWlncmFudHMiCmF1dGhvcjogIkplbnMgdm9uIEJlcmdtYW5uIgpkYXRlOiAiMjAxNy0wOC0yNiIKb3V0cHV0OiBodG1sX25vdGVib29rCnZpZ25ldHRlOiA+CiAgJVxWaWduZXR0ZUluZGV4RW50cnl7UmVjZW50IEltbWlncmFudHN9CiAgJVxWaWduZXR0ZUVuZ2luZXtrbml0cjo6cm1hcmtkb3dufQogICVcVmlnbmV0dGVFbmNvZGluZ3tVVEYtOH0KLS0tCgpNdWx0aS1jYXRlZ29yeSBkb3QtZGVuc2l0eSBtYXBzIG9mdGVuIHdvcmsgd2VsbCB3aGVuIHRoZSBjYXRlZ29yaWVzIGNsdXN0ZXIgZ2VvZ3JhcGhpY2FsbHkuIFJlY2VudCBpbW1pZ3JhbnRzIGJ5CmNvdW50cnkgb2Ygb3JpZ2luIHdvcmsgd2VsbCBmb3IgdGhpcy4KIyMgRGF0YQpGaXJzdCB3ZSBncmFiIHRoZSBpbW1pZ3JhbnQgZGF0YSB2aWEgW2NhbmNlbnN1c10oaHR0cHM6Ly9naXRodWIuY29tL21vdW50YWluTWF0aC9jYW5jZW5zdXMpLCBtYWtpbmcgdXNlIG9mIHRoZSBbQ2Vuc3VzTWFwcGVyIEFQSSB0b29sXShodHRwczovL2NlbnN1c21hcHBlci5jYS9hcGkvQ0ExMSkgdG8gc2VsZWN0IHRoZSByZWdpb25zIGFuZCB2YXJpYWJsZXMgd2UgbmVlZC4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoIm1vdW50YWlubWF0aC9jYW5jZW5zdXMiKQpsaWJyYXJ5KGNhbmNlbnN1cykKbGlicmFyeShkb3RkZW5zaXR5KQojIG9wdGlvbnMoY2FuY2Vuc3VzLmFwaV9rZXk9J3lvdXJfYXBpX2tleScpCnJlZ2lvbnM9bGlzdChDTUE9IjU5OTMzIikKdmVjdG9yc18yMDExPWMoInZfQ0ExMU5fMjY1Iiwidl9DQTExTl8yNjgiLCJ2X0NBMTFOXzMwNCIsInZfQ0ExMU5fMzM0Iiwidl9DQTExTl8zNzMiLCJ2X0NBMTFOXzM3NiIsInZfQ0ExMU5fMzc5Iiwidl9DQTExTl8zODIiKQp2ZWN0b3JzPWMoInZfQ0ExNl8zNjM2Iiwidl9DQTE2XzM2MzkiLCJ2X0NBMTZfMzY2OSIsInZfQ0ExNl8zNjk5Iiwidl9DQTE2XzM3NDEiLCJ2X0NBMTZfMzgxMCIsInZfQ0ExNl8zNzUwIiwidl9DQTE2XzM3NTYiLCJ2X0NBMTZfMzc4MyIpCmBgYAoKV2UgY2hvb3NlIHRoZSBjYXRlZ29yaWVzIGFuZCBjb2xvdXJzIHdlIHdhbnQgdG8gbWFwIGFuZCBkZWZpbmUgYSBjb252ZW5pZW5jZSBmdW5jdGlvbiB0byByZW5hbWUgdGhlIHZhcmlhYmxlcyBhbmQgY29tcHV0ZSB0aGUgcWFudGl0aWVzIGZvciB0aGUgb3RoZXIgYXNpYW4gY291bnRyaWVzIHRoYXQgd2UgZG9uJ3QgYnJlYWsgb3V0LgpgYGB7cn0KY2F0ZWdvcmllcz1jKCJBbWVyaWNhcyIsIkV1cm9wZSIsIkFmcmljYSArIE9jZWFuaWEiLCJQaGlsaXBwaW5lcyIsIkNoaW5hIiwiSW5kaWEiLCJPdGhlciBBc2lhbiBDb3VudHJpZXMiKQpjb2xvcnM9YygiIzdhMDE3NyIsICIjMzMzM2NjIiwgIiNmZjAwZmYiLCAiIzAwZmZmZiIsICIjZmYxYTFjIiwgIiM0ZGZmNGEiLCAiI2ZmZmYzMyIpCgpwcmVwX2RhdGEgPC0gZnVuY3Rpb24oZ2VvKXsKICBkYXRhIDwtIGdlb0BkYXRhICU+JSByZXBsYWNlKGlzLm5hKC4pLCAwKQogIGRhdGEgPC0gcmVuYW1lKGRhdGEsCiAgICB0b3RhbD12X0NBMTZfMzYzNiwKICAgIEFtZXJpY2FzPXZfQ0ExNl8zNjM5LCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIEV1cm9wZT12X0NBMTZfMzY2OSwKICAgIFBoaWxpcHBpbmVzPXZfQ0ExNl8zNzgzLAogICAgQ2hpbmE9dl9DQTE2XzM3NTAsCiAgICBJbmRpYT12X0NBMTZfMzc1NikKICBkYXRhIDwtIG11dGF0ZShkYXRhLGBPdGhlciBBc2lhbiBDb3VudHJpZXNgID0gdl9DQTE2XzM3NDEtUGhpbGlwcGluZXMtQ2hpbmEtSW5kaWEsCiAgICAgICAgICAgICAgICAgICAgIGBBZnJpY2EgKyBPY2VhbmlhYD12X0NBMTZfMzY5OSArIHZfQ0ExNl8zODEwKQogIGdlb0BkYXRhIDwtIGRhdGEKICByZXR1cm4oZ2VvKQp9CnByZXBfZGF0YV8yMDExIDwtIGZ1bmN0aW9uKGdlbyl7CiAgZGF0YSA8LSBnZW9AZGF0YSAlPiUgcmVwbGFjZShpcy5uYSguKSwgMCkKICBkYXRhIDwtIHJlbmFtZShkYXRhLAogICAgdG90YWw9dl9DQTExTl8yNjUsCiAgICBBbWVyaWNhcz12X0NBMTFOXzI2OCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBFdXJvcGU9dl9DQTExTl8zMDQsCiAgICBBZnJpY2E9dl9DQTExTl8zMzQsCiAgICBQaGlsaXBwaW5lcz12X0NBMTFOXzM3NiwKICAgIENoaW5hPXZfQ0ExMU5fMzc5LAogICAgSW5kaWE9dl9DQTExTl8zODIpCiAgZGF0YSA8LSBtdXRhdGUoZGF0YSxgT3RoZXIgQXNpYW4gQ291bnRyaWVzYCA9IHZfQ0ExMU5fMzczLVBoaWxpcHBpbmVzLUNoaW5hLUluZGlhKQogIGdlb0BkYXRhIDwtIGRhdGEKICByZXR1cm4oZ2VvKQp9CmBgYAoKCk5leHQgd2UgZ3JhYiB0aGUgZGF0YSB2aWEgYGNhbmNlbnN1c2AsCmBgYHtyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRhdGFfY3NkPWdldF9jZW5zdXMoZGF0YXNldCA9ICdDQTE2JywgcmVnaW9ucz1yZWdpb25zLHZlY3RvcnM9dmVjdG9ycyxnZW9fZm9ybWF0PSdzcCcsbGFiZWxzPSdzaG9ydCcsbGV2ZWw9J0NTRCcpICU+JSBwcmVwX2RhdGEKZGF0YV9jdD1nZXRfY2Vuc3VzKGRhdGFzZXQgPSAnQ0ExNicsIHJlZ2lvbnM9cmVnaW9ucyx2ZWN0b3JzPXZlY3RvcnMsZ2VvX2Zvcm1hdD0nc3AnLGxhYmVscz0nc2hvcnQnLGxldmVsPSdDVCcpICU+JSBwcmVwX2RhdGEKZGF0YV9kYT1nZXRfY2Vuc3VzKGRhdGFzZXQgPSAnQ0ExNicsIHJlZ2lvbnM9cmVnaW9ucyx2ZWN0b3JzPXZlY3RvcnMsZ2VvX2Zvcm1hdD0nc3AnLGxhYmVscz0nc2hvcnQnLGxldmVsPSdEQScpICU+JSBwcmVwX2RhdGEKZGF0YV9kYj1nZXRfY2Vuc3VzKGRhdGFzZXQgPSAnQ0ExNicsIHJlZ2lvbnM9cmVnaW9ucyxnZW9fZm9ybWF0PSdzcCcsbGFiZWxzPSdzaG9ydCcsbGV2ZWw9J0RCJykKYGBgCgp3aGljaCB3ZSB0aGVuIHJlLWFnZ3JlZ2F0ZSB0byBtYWtlIHN1cmUgd2UgZG9uJ3QgbWlzcyBvdmVyYWxsIGNvdW50cyBkdWUgdG8gcHJpdmFjeSBjdXRvZmZzIGRpc3RyaWJ1dGUgdGhlbQpwcm9wb3J0aW9uYWxseSBhbW9uZyB0aGUgcG9wdWxhdGlvbi4KYGBge3J9CmRhdGFfY3RAZGF0YSA8LSBkb3RfZGVuc2l0eS5wcm9wb3J0aW9uYWxfcmVfYWdncmVnYXRlKGRhdGE9ZGF0YV9jdEBkYXRhLHBhcmVudF9kYXRhPWRhdGFfY3NkQGRhdGEsZ2VvX21hdGNoPXNldE5hbWVzKCJHZW9VSUQiLCJDU0RfVUlEIiksY2F0ZWdvcmllcz1jYXRlZ29yaWVzLGJhc2U9IlBvcHVsYXRpb24iKQpkYXRhX2RhQGRhdGEgPC0gZG90X2RlbnNpdHkucHJvcG9ydGlvbmFsX3JlX2FnZ3JlZ2F0ZShkYXRhPWRhdGFfZGFAZGF0YSxwYXJlbnRfZGF0YT1kYXRhX2N0QGRhdGEsZ2VvX21hdGNoPXNldE5hbWVzKCJHZW9VSUQiLCJDVF9VSUQiKSxjYXRlZ29yaWVzPWNhdGVnb3JpZXMsYmFzZT0iUG9wdWxhdGlvbiIpCmRhdGFfZGJAZGF0YSA8LSBkb3RfZGVuc2l0eS5wcm9wb3J0aW9uYWxfcmVfYWdncmVnYXRlKGRhdGE9ZGF0YV9kYkBkYXRhLHBhcmVudF9kYXRhPWRhdGFfZGFAZGF0YSxnZW9fbWF0Y2g9c2V0TmFtZXMoIkdlb1VJRCIsIkRBX1VJRCIpLGNhdGVnb3JpZXM9Y2F0ZWdvcmllcyxiYXNlPSJQb3B1bGF0aW9uIikKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKYmdfY29sb3I9IiMxMTExMTEiCmJhc2VfY29sb3I9IiMzMzMzMzMiCnRleHRfY29sb3I9IiNlZWVlZWUiCnRoZW1lX29wdHM8LWxpc3QodGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IGJnX2NvbG9yLCBjb2xvdXIgPSBOQSksCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9YmdfY29sb3IsIHNpemU9MSxsaW5ldHlwZT0ic29saWQiLGNvbG9yPXRleHRfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTcwLGhqdXN0ID0gMC41LCBjb2xvcj10ZXh0X2NvbG9yKSwKICAgICAgICAgICAgICAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9NTAsaGp1c3QgPSAwLjUsIGNvbG9yPXRleHRfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplPTI1LCBjb2xvcj10ZXh0X2NvbG9yKSwKICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0zNSwgY29sb3I9dGV4dF9jb2xvciksCiAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0zNSwgY29sb3I9dGV4dF9jb2xvciksCiAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD1iZ19jb2xvciwgc2l6ZT0xLGxpbmV0eXBlPSJzb2xpZCIsY29sb3I9YmdfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9IGJnX2NvbG9yLGNvbG9yID0gYmdfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDMsICdsaW5lcycpLAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSkKCmJhc2VtYXAgPC0gICBnZ3Bsb3QoZGF0YV9jc2QpICsKICAgIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbCA9IGJhc2VfY29sb3IsIHNpemU9MC4xLCBjb2xvciA9ICdncmV5JykgKwogICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChucm93PTEsb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTE1KSkpICsKICAgIGNvb3JkX21hcChwcm9qZWN0aW9uPSJsYW1iZXJ0IiwgbGF0MD00OSwgbGF0PTQ5LjQpICsKICAgIHRoZW1lX29wdHMKCmBgYAoKCiMjTWFwCkFsbCB0aGF0J3MgbGVmdCB0byBkbyBpcyB0byBjb3ZlcnQgb3VyIHJlLWFnZ3JlZ2F0ZWQgYmxvY2stbGV2ZWwgZGF0YSB0byBkb3RzLCB1c2luZyB0aGUgYGRvdF9kZW5zaXR5LmNvbXB1dGVfZG90c2AKZnVuY3Rpb24gZnJvbSB0aGUgW2Bkb3RkZW5zaXR5YCBwYWNrYWdlXSgpIGFuZCBmZWVkIGl0IGludG8gdGhlIGBkb3RfZGVuc2l0eS5kb3RzX21hcGAgZnVuY3Rpb24gdG8gYWRkIHRoZW0gdG8Kb3VyIGJhc2VtYXAuCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTMsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1UUlVFfQojIDEgZG90ID0gNSBpbW1pZ3JhbnRzCnNjYWxlPTUKCgpkb3RzLmRiIDwtIGRvdF9kZW5zaXR5LmNvbXB1dGVfZG90cyhnZW9fZGF0YSA9IGRhdGFfZGIsIGNhdGVnb3JpZXMgPSBjYXRlZ29yaWVzLCBzY2FsZT1zY2FsZSkKYmFzZW1hcCArCiAgIyB6b29tIGluIGEgYml0CiAgY29vcmRfZml4ZWQoeGxpbT1jKC0xMjMuMjksLTEyMi42KSwgeWxpbT1jKDQ5LjAyLDQ5LjM1KSwgcmF0aW8gPSAxL2Nvcyg0OS4yLzE4MCpwaSkpICsKIyBzaGFkZSB1bnBvcHVsYXRlZCBibG9ja3MKIyAgZ2VvbV9wb2x5Z29uKGRhdGE9ZGF0YV9kYltkYXRhX2RiJFBvcHVsYXRpb248PTUsXSwgCiMgICAgICAgICAgICAgICAgICAgICAgICBhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSwgCiMgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gIiMyMjIyMjIiLCBzaXplPTAuMSwgCiMgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMjIyMjIyIikgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29sb3JzKSArCiAgbGFicyhjb2xvciA9ICIiLAogICAgICAgICAgICAgICAgdGl0bGU9IkltbWlncmFudHMgMjAxMSAtIDIwMTYiLAogICAgICAgICAgICAgICAgY2FwdGlvbj0iU291cmNlOiBTdGF0Q2FuIENlbnN1cyAyMDE2IHZpYSBjYW5jZW5zdXMgJiBDZW5zdXNNYXBwZXIuY2EiLAogICAgICAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIjEgZG90ID0gIixzY2FsZSwiIHBlb3BsZSIpKSArIAogIGRvdF9kZW5zaXR5LmRvdHNfbWFwKGRvdHM9ZG90cy5kYixhbHBoYT0wLjc1LHNpemU9MC4yNSkKCiMgc2F2ZSBpbWFnZSBmb3IgbGF0ZXIKZ2dzYXZlKCcuLi9pbWFnZXMvcmVjZW50X2ltbWlncmFudHMucG5nJyx3aWR0aD0yNixoZWlnaHQ9MjYpCmBgYAoK